<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <!-- Meta, title, CSS, favicons, etc. -->
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="avalonjs - 迷你简单易用的前端MVVM框架，让你的网站更快更炫更好用">
        <meta name="keywords" content="MVVM, CSS, JavaScript, framework, avalon, web development">
        <meta name="author" content="RubyLouvre,司徒正美">


        <title>avalon中文文档</title>
        <script src="//files.cnblogs.com/files/rubylouvre/avalon.shim.js"></script>

        <!-- Bootstrap core CSS -->
        <link href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">

        <link href="../../assets/css/patch.css" rel="stylesheet">

        <!-- Documentation extras -->

        <link href="../../assets/css/docs.min.css" rel="stylesheet">
        <style>
            body,html{
               overflow-y: hidden;
            }
        </style>
        <!--[if lt IE 9]><script src="../assets/js/ie8-responsive-file-warning.js"></script>
        <script src="../../assets/js/ie-emulation-modes-warning.js"></script>
        <![endif]-->
        <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
        <!--[if lt IE 9]>
          <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
          <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
        <![endif]-->

        <!-- Favicons -->
        <link rel="apple-touch-icon" href="/apple-touch-icon.png">
        <link rel="icon" href="/favicon.ico">

    </head>
    <body>




        <div class="container bs-docs-container">

            <div class="row">
                <div class="col-md-9" role="main">

<h2>模板引用(ms-include)</h2>
<p>稍为复杂一点的网站都是多个前端工程师合作而成，因此分工是必需的。简单一点的分工就是一个人负责一个频道，某个页面是由一个人全部做的；但如果涉及到一个页面非常复杂，需要多个人同时动工呢？于是到模板的出场时间了。</p>

<p>模板有两种，一种是嵌入到页面内的模板，一种是独立成子页面的模板。这两种avalon都支持。前者通常是使用type为浏览器无法识别的MIME类型的script标签，display:none的textarea标签或noscript标签（0.94后支持，建议使用它）作为模板容器，最近HTML5出了一个新的template标签，大家也不妨用一用。一般情况下，它是用于放置弹出层的内容。另一个模板，则需要通过AJAX请求来加载它们，它们适用范围更广，并且重用性更好。</p>

<p>对于页面内的模板，我们可以使用<strong>ms-include=&#8221;expr&#8221;</strong>绑定，对于独立于页面的模板，我们可以使用<strong>ms-include-src=&#8221;expr&#8221;</strong>绑定。ms-include要求对应一个<strong>ID</strong>（换言之，作为模板容器的script等标签必须指定ID），ms-include-src要求对应一个<strong>路径</strong>。需要注意的是ms-include或ms-include-src的属性值默认都是对应VM的一个属性，当作是一个变量，如果想直接使用字符串，那么需要使用<strong>双重引号</strong>。</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;meta http-equiv="content-type" content="text/html; charset=UTF-8" /&gt;
    &lt;script src="avalon.js"&gt;&lt;/script&gt;
    &lt;script&gt;
        var model = avalon.define({
            $id: "test",
            content: "引入内部模板",
            name: "司徒正美",
            eee: "lala",
            change: function() {
                model.eee = model.eee === "lala" ? "hehe" : "lala"
            }
        })
    &lt;/script&gt;
&lt;/head&gt;

&lt;body ms-controller="test"&gt;
    &lt;script type="avalon" id="tpl"&gt;
        here, {{ 3 + 6 * 5 }}
    &lt;/script&gt;
    &lt;script type="avalon" id="lala"&gt;
        &lt;strong&gt;{{name}}&lt;/strong&gt;!!!
    &lt;/script&gt;
    &lt;script type="avalon" id="hehe"&gt;
        &lt;em&gt;{{content}}&lt;/em&gt;!!!
    &lt;/script&gt;
    &lt;p&gt;{{content}}
        &lt;button ms-click="change" type="button"&gt;切换子模板&lt;/button&gt;
    &lt;/p&gt;
    &lt;div ms-include="'tpl'"&gt;&lt;/div&gt;
    &lt;!--注意这里--&gt;
    &lt;div ms-include="eee"&gt;&lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;</pre></div>

<p><img src="../../assets/css/directives/include/1409809489146-include.gif" /></p>
<p>ms-include与ms-include-src的属性值可以添加插值表达式，见下面例子，不过注意需要打开服务器，因为用到AJAX请求。</p>

<p>有四个页面，一个主页面与三个独立的子模板，它们都放在一起，内容分别如下。</p>

<p>include.html</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=Edge" /&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
    &lt;title&gt;ms-include&lt;/title&gt;
    &lt;script src="../avalon.js"&gt;&lt;/script&gt;
    &lt;script&gt;
        var model = avalon.define({
            $id: "test",
            url: "Template1",
            name: "司徒正美",
            password: '12345678',
            array: [1, 2, 3, 4, 5, 6, 7],
            add: function(e) {
                if (this.value & amp; & amp; e.which == 13) { //this为input元素
                    var a = this.value
                    model.array.push(a)
                    this.value = "";
                }
            }
        })
    &lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h3 style='text-align: center'&gt;ms-include&lt;/h3&gt;
    &lt;div ms-controller="test"&gt;
        &lt;select ms-duplex="url"&gt;
            &lt;option&gt;Template1&lt;/option&gt;
            &lt;option&gt;Template2&lt;/option&gt;
            &lt;option&gt;Template3&lt;/option&gt;
        &lt;/select&gt;
        &lt;div ms-include-src="include{{url}}.html"&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;</pre></div>

<p>includeTemplate1.html</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;h1&gt;这是模板1&lt;/h1&gt;
&lt;p&gt;生成于{{ new Date | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;
&lt;p&gt;生成于{{ "2011/07/08" | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;
&lt;p&gt;生成于{{ "2011-07-08" | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;
&lt;p&gt;生成于{{ "01-10-2000" | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;
&lt;p&gt;生成于{{ "07 04,2000" | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;
&lt;p&gt;生成于{{ "3 14,2000" | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;
&lt;p&gt;生成于{{ 1373021259229 | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;
&lt;p&gt;生成于{{ "1373021259229" | date("yyyy MM dd:HH:mm:ss")}}&lt;/p&gt;</pre></div>
<p>值得注意的是，new Date可传的格式类型非常多，但不是所有浏览器都支持这么多，详看<a href="http://dygraphs.com/date-formats.html">这里</a>。</p>

<p>includeTemplate2.html</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;script type="avalon" id='form'&gt;
    &lt;p&gt;姓名：
        &lt;input ms-duplex="name"&gt;{{name}}&lt;/p&gt;
    &lt;p&gt;密码：
        &lt;input type="password" ms-duplex="password" /&gt;{{password}}&lt;/p&gt;
&lt;/script&gt;
&lt;form ms-include="'form'" style='border:1px solid #666;background:sandybrown;padding:20px'&gt;

&lt;/form&gt;</pre></div>

<p>includeTemplate3.html</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;ul ms-each-el="array"&gt;
    &lt;li&gt;第 {{$index+1}} 个元素: {{el}} &lt;span ms-click="$remove"&gt;点我删除&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;添加新元素 ，然后回车
    &lt;input ms-keypress="add"&gt;
&lt;/p&gt;</pre></div>

<p><img src="../../assets/css/directives/include/1409809507647-include2.gif"  /></p>

<p>如果大家想在模板加载后，加工一下模板，可以使用data-include-loaded来指定回调的名字。</p>

<p>如果大家想在模板扫描后，隐藏loading什么的，可以使用data-include-rendered来指定回调的名字。</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;title&gt;ms-include相关实验&lt;/title&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
    &lt;script src="avalon.js"&gt;
    &lt;/script&gt;
    &lt;script&gt;
        avalon.define("test", function(vm) {
            vm.render = function() {
                console.log("render")
            }
        })
    &lt;/script&gt;
&lt;/head&gt;

&lt;body ms-controller="test"&gt;
    &lt;div ms-include-src="'temp.html'" data-include-rendered='render'&gt;&lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;</pre></div>

<p>temp.html</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;title&gt;TODO supply a title&lt;/title&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width"&gt;
    &lt;script&gt;
        console.log("----------")
    &lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div&gt;include content&lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;</pre></div>

<p><img src="../../assets/css/directives/include/1409810730376-include3.png" /></p>

<p>我们看<code>avalon.templateCache</code>，所有ms-include-src加载的模板都会缓存在这里，从而有效地减少请求数。
  并且这个东西还有一个额外的好处，我们的JS与CSS最终会压缩合并，对于这些模板我们也想把它们合并到JS文件里面，
  它就有用武之地了。这也是我们在第一节看到的那样，把requirejs加载回来的模板都放在<code>avalon.templateCache</code>里，
  与ms-include-src一起使用了。</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;title&gt;avalon.templateCache的应用&lt;/title&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width"&gt;
    &lt;script src="avalon.js"&gt;&lt;/script&gt;
    &lt;script&gt;
        avalon.templateCache["aaa.html"] = "&lt;strong&gt;dddddddddddd&lt;/strong&gt;"
        avalon.templateCache["bbb.html"] = "&lt;em&gt;555555555555&lt;/em&gt;"

        var model = avalon.define({
            $id: "test",
            adjust: function(tmpl) {
                return tmpl + "  " + (new Date - 0)
            },
            aaa: "aaa.html",
            change: function() {
                model.aaa = model.aaa === "aaa.html" ? "bbb.html" : "aaa.html"
            }
        })
    &lt;/script&gt;
&lt;/head&gt;

&lt;body ms-controller="test"&gt;
    &lt;div ms-include-src="aaa" data-include-loaded="adjust"&gt;&lt;/div&gt;
    &lt;button type="button" ms-click="change"&gt;点我切换模板&lt;/button&gt;
&lt;/body&gt;

&lt;/html&gt;</pre></div>

<p><img src="../../assets/css/directives/include/1409812441030-include4.gif"  /></p>
<div class="bs-callout bs-callout-info" >
  <p>在avalon1.3.7中添加一个辅助指令data-include-replace，当其值为真，它就会加载模板后自动替代掉其原父容器节点。
  主页面</p>
</div>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;title&gt;duplexHooks&lt;/title&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=8" /&gt;
    &lt;script src="../avalon.modern.js"&gt;&lt;/script&gt;
    &lt;style&gt;
        .bp {
            border: 1px solid green;
        }
        
        .contain {
            border: 1px solid red;
        }
    &lt;/style&gt;
    &lt;script&gt;
        var a = avalon.define({
            $id: "test",
            aaa: "aaa.html",
            change: function() {
                a.aaa = a.aaa === "aaa.html" ? "bbb.html" : "aaa.html"
            }
        })
    &lt;/script&gt;
&lt;/head&gt;

&lt;body ms-controller="test"&gt;
    &lt;button type="button" ms-click="change"&gt;change&lt;/button&gt;
    &lt;div ms-include-src="'include2'+aaa" class="contain"&gt;&lt;/div&gt;
    &lt;div ms-include-src="'include2'+aaa" class="contain" data-include-replace="true"&gt;&lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;</pre></div>

<p>include2aaa.html</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;div&gt;
    xxxxxxxxxxxxx&lt;/div&gt;
&lt;div&gt;yyyyyyyyyyyy&lt;/div&gt;</pre></div>

<p>include2bbb.html</p>

<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;p class="bp"&gt;
    aaaaaaaaaaa&lt;/p&gt;
&lt;p class="bp"&gt;bbbbbbbbbbb&lt;/p&gt;
&lt;p class="bp"&gt;ccccccccccc&lt;/p&gt;</pre></div>

<p><img src="../../assets/css/directives/include/1414724133046-include-replace.gif" /></p>
<p>我们结合data-include-rendered, ms-repeat, ms-include实现一个网易式的评论呈现树吧</p>
<div ms-skip style='background:rgb(237,237,237);padding:4px;'><pre class='brush:html;gutter:false;toolbar:false'>&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;title&gt;TODO supply a title&lt;/title&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width"&gt;
    &lt;script src="avalon.js"&gt;&lt;/script&gt;
    &lt;style&gt;
        .level_even {
            background: #ccc;
        }
        
        .level_odd {
            background: #fff;
        }
    &lt;/style&gt;
    &lt;script&gt;
        var array = [{
            children: [],
            author: "第一层a"
        }, {
            children: [],
            author: "第一层b"
        }];
        array[0].children.push({
            children: [],
            author: "第二层a"
        }, {
            children: [],
            author: "第二层b"
        })
        array[0].children[0].children.push({
            children: [],
            author: "第三层a"
        }, {
            children: [],
            author: "第三层b"
        })
        array[0].children[0].children[0].children.push({
            children: [],
            author: "第四层a"
        }, {
            children: [],
            author: "第四层b"
        }, {
            children: [],
            author: "第四层c"
        })
        var vm = avalon.define({
            $id: "test",
            aaa: "通过ms-repeat, ms-include实现树",
            array: array,
            addClass: function() {
                var level = 0
                var parent = this.parentNode
                do {
                    if (parent.tagName == "UL") {
                        level++
                    }
                    if (parent.tagName === "BODY") {
                        break
                    }
                } while (parent = parent.parentNode)
                avalon(this).addClass("level_" + level)
                avalon(this).addClass(level % 2 === 0 ? "level_even" : "level_odd")
            }
        })
    &lt;/script&gt;
&lt;/head&gt;

&lt;body ms-controller="test"&gt;
    &lt;h2&gt;{{aaa}}&lt;/h2&gt;
    &lt;script type="avalon" id="comments"&gt;
        &lt;ul&gt;
            &lt;li ms-repeat="el.children"&gt;
                {{el.author}}
                &lt;div ms-if="el.children.size()" ms-include="'comments'" data-include-rendered='addClass'&gt; &lt;/div&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
    &lt;/script&gt;
    &lt;div class='level_0 level_even'&gt;
        &lt;ul&gt;
            &lt;li ms-repeat="array"&gt;
                {{el.author}}
                &lt;div ms-if="el.children.size()" ms-include="'comments'" data-include-rendered='addClass'&gt;&lt;/div&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;</pre></div>
<p><img src="../../assets/css/directives/include/include2.png"  /></p>
<p>avalon1.4.2中，添加了data-include-cache="true"辅助指令，它会保存之前的模板被扫描后的DOM节点。</p>
<xml class="html">
<!DOCTYPE html>
<html>
    <head>
        <title>data-include-cache="true"</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <script src="avalon.js"></script>
        <script>
            var vm = avalon.define({
                $id: "test",
                aaa: "",
                changeA: function () {
                    vm.aaa = "aaa"
                },
                changeB: function () {
                    vm.aaa = "bbb"
                },
                changeC: function () {
                    vm.aaa = "ccc"
                }
            })
        </script>
        <script type="avalon" id="aaa">
            <h2>这是模板1</h2>
    {{new Date - 0}}
        </script>
        <script type="avalon" id="bbb">
          <h2>这是模板2</h2>
  {{new Date - 0}}
        </script>
        <script type="avalon" id="ccc">
            <h2>这是模板3</h2>
    {{new Date - 0}}
        </script>
    </head>
    <body>
        <div ms-controller="test">
            <div ms-include="aaa" data-include-cache="true">准备加载模块....</div>
            <p>
                <button type="button" ms-click="changeA">aaa</button>
                <button type="button" ms-click="changeB">bbb</button>
                <button type="button" ms-click="changeC">ccc</button>
            </p>
        </div>
    </body>
</html>
</xmp>


</div>
<div class="col-md-3" role="complementary">

</div>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="../../assets/highlight/shCore.js"></script>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
</body>
</html>

